package org.common.utils.nacos;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import org.common.utils.nacos.entity.NacosAddress;
import org.common.utils.nacos.exception.NacosAccessException;
import org.common.utils.tool.StringTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

/**
 * @author zhouzhibing
 * @date 2025/6/13
 */
public class NacosTool {
    private static final Logger log = LoggerFactory.getLogger(NacosTool.class);

    /**
     * 创建一个nacos配置服务
     * @param nacosAddress nacos地址
     * @return NacosConfigService
     */
    public static ConfigService createConfigService(NacosAddress nacosAddress) {
        Properties properties = createProperties(nacosAddress);
        try {
            return NacosFactory.createConfigService(properties);
        } catch (NacosException e) {
            log.error("NacosTool.createConfigService error , nacosAddress = {}" , nacosAddress , e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建一个nacos命名服务
     * @param nacosAddress nacos地址
     * @return NacosNamingService
     */
    public static NamingService createNamingService(NacosAddress nacosAddress) {
        Properties properties = createProperties(nacosAddress);
        try {
            return NacosFactory.createNamingService(properties);
        } catch (NacosException e) {
            log.error("NacosTool.createNamingService error , nacosAddress = {}" , nacosAddress , e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建一个nacos配置属性
     * @param nacosAddress nacos地址
     * @return nacos属性
     */
    private static Properties createProperties(NacosAddress nacosAddress) {
        checkParameters(nacosAddress);

        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosAddress.getHost());
        properties.setProperty(PropertyKeyConst.NAMESPACE, nacosAddress.getNamespace());

        if(!StringTool.isEmpty(nacosAddress.getUsername()) && !StringTool.isEmpty(nacosAddress.getPassword())) {
            properties.setProperty(PropertyKeyConst.USERNAME, nacosAddress.getUsername());
            properties.setProperty(PropertyKeyConst.PASSWORD, nacosAddress.getPassword());
        }

        if(!StringTool.isEmpty(nacosAddress.getAccessKey()) && !StringTool.isEmpty(nacosAddress.getSecretKey())) {
            properties.setProperty(PropertyKeyConst.ACCESS_KEY, nacosAddress.getAccessKey());
            properties.setProperty(PropertyKeyConst.SECRET_KEY, nacosAddress.getSecretKey());
        }

        threadConfig(properties);
        return properties;
    }

    /**
     * 线程参数配置
     * @param nacosProperties 参数列表
     */
    private static void threadConfig(Properties nacosProperties) {
        int coreSize = Runtime.getRuntime().availableProcessors();
        String minCount = Math.max(1 , coreSize / 4) + "";
        String maxCount = Math.max(1 , coreSize / 2) + "";

        nacosProperties.put(PropertyKeyConst.CLIENT_WORKER_THREAD_COUNT, minCount);
        nacosProperties.put(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT, maxCount);

        nacosProperties.put(PropertyKeyConst.CLIENT_WORKER_MAX_THREAD_COUNT, minCount);
        nacosProperties.put(PropertyKeyConst.NAMING_POLLING_MAX_THREAD_COUNT, maxCount);

        nacosProperties.put("nacos.grpc.client.threadPool.coreSize", minCount);
        nacosProperties.put("nacos.grpc.client.threadPool.maxSize", maxCount);

        System.setProperty("nacos.remote.client.grpc.pool.core.size" , minCount);
        System.setProperty("nacos.remote.client.grpc.pool.max.size" , maxCount);
        System.setProperty("nacos.remote.client.grpc.pool.alive" , "30000");
    }

    /**
     * 检查参数
     * @param nacosAddress nacos地址
     */
    private static void checkParameters(NacosAddress nacosAddress) {
        if(StringTool.isEmpty(nacosAddress.getUsername())) {
            throw new NacosAccessException("username empty !");
        }

        if(StringTool.isEmpty(nacosAddress.getPassword())) {
            throw new NacosAccessException("password empty !");
        }

        if(StringTool.isEmpty(nacosAddress.getHost())) {
            throw new NacosAccessException("host empty !");
        }

        if(StringTool.isEmpty(nacosAddress.getNamespace())) {
            throw new NacosAccessException("namespace empty !");
        }

        if (!StringTool.isEmpty(nacosAddress.getAccessKey())) {
            if(StringTool.isEmpty(nacosAddress.getSecretKey())) {
                throw new NacosAccessException("accessKey not empty, but secretKey epmty !");
            }
        }

        if (!StringTool.isEmpty(nacosAddress.getSecretKey())) {
            if(StringTool.isEmpty(nacosAddress.getAccessKey())) {
                throw new NacosAccessException("secretKey not empty, but accessKey epmty !");
            }
        }

        log.info("NacosTool.checkParameters success , nacosAddress = {}" , nacosAddress);
    }


}
